Skip to content

Conversation

@nytian
Copy link
Contributor

@nytian nytian commented Mar 19, 2025

This PR partially solves issue Azure/azure-functions-durable-extension#2689

This PR adds a new exception type Microsoft.DurableTask.SubOrchestrationFailedException. Previously, SubOrchestrationFailedException was included with the TaskFailedException, and it's now handled separately with this new type.

For example, if cx want custom handling logic specifically for suborchestration failures, they should write a catch block for SubOrchestrationFailedException instead of the broader TaskFailedException.

try
{
    await ctx.CallActivityAsync("myactivity");
    await ctx.CallSubOrchestratorAsync("mysuborch");
}
catch (SubOrchestrationFailedException ex)
{
    // Handle suborchestration-specific exceptions here
}
catch (TaskFailedException ex)
{
    // Handle other task failures here, including Activities, non-deterministic etc
}

@nytian nytian requested review from cgillum and jviau March 19, 2025 20:39
Copy link
Collaborator

@andystaples andystaples left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments

coreEx.GetType().ToString(),
coreEx.Message,
coreEx.StackTrace,
FromCoreFailureDetailsRecursive(coreEx.FailureDetails?.InnerFailure) ?? FromExceptionRecursive(coreEx.InnerException));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be
FromCoreFailureDetailsRecursive(coreEx.FailureDetails) ?? FromExceptionRecursive(coreEx.InnerException))
To prevent loss of the outer FailureDetails?

// Outer failure represents the orchestration failure
Assert.NotNull(ex.FailureDetails);
Assert.True(ex.FailureDetails.IsCausedBy<TaskFailedException>());
Assert.Contains("ThrowException", ex.FailureDetails.ErrorMessage);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change worries me - our tests were checking that the activity name was present in the exception message, which I think is important. Even if this change means that this information is in some InnerFailure, can we still make sure that this information is present somewhere in the exception details?

Assert.NotNull(ex.FailureDetails);
Assert.True(ex.FailureDetails.IsCausedBy<TaskFailedException>());
Assert.Contains("ThrowException", ex.FailureDetails.ErrorMessage);
Assert.True(ex.FailureDetails.IsCausedBy<CoreSubOrchestrationFailedException>());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to expose any DurableTask.Core types in the .NET Isolated model. Also, this is a breaking change so I think we need to rethink this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah what I’m mainly worried about with this change is that it looks like we don’t want to expose any core exception types here, though I’m not sure why.
I’m totally fine with closing this. I made this change mainly because it’s what the issue/customer was asking for and with this change it seemed more in line with our in-proc model. But it seems like we just want to show that the sub-orchestrator failed in the error message, not the actual error type, is that correct?

Copy link
Member

@jviau jviau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't expose any DurableTask.Core types to the user in this repo, we want to keep that purely an implementation detail. Please derive a new exception type in this repo and construct that from the SubOrchestrationFailedException instead

@nytian nytian changed the title Expose type SubOrchestrationFailedException in FailureDetails of TaskFailedException Add Exception Type SubOrchestrationFailedException Mar 25, 2025
@nytian nytian marked this pull request as draft March 25, 2025 15:22
@nytian nytian marked this pull request as ready for review March 25, 2025 19:44
@nytian
Copy link
Contributor Author

nytian commented Mar 25, 2025

After further discussing and consideration, this PR should be closed. The main reason is that our current approach—throwing TaskFailedException for all failed tasks—is consistent with the existing in-proc model, which always throws FunctionsFailedException. Changing this behavior might unexpectedly break errors handling of all Durable Functions. Also, detailed information about task failures or the specific functions that threw exceptions can already be obtained from the error message itself, and does not necessarily require differentiating exception types.

@nytian nytian closed this Mar 25, 2025
@nytian nytian deleted the nytian/failure-details branch September 30, 2025 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants